/*

Things to be done yet....

    InEditorInfo and SetupInfoBar-  I don't have the current gospel on
        interfacing with fColorPalette, so these have to be completed.
        (Setup does a silent load of the Tool Picture, In Editor Info
         does the actual interaction)

    We need to build the prototype list for the front end.

Problems to deal with
    1.  I like the idea of using a pic rather than a full reconstruct and
        write to handle undo.  However, to manage this, bearing in mind
        mask interaction, what we would need to do is set up the picture
        containing our undo image to be 2x the width (or height for that
        matter) of the icon image itself, the extra area containing a copy
        of the mask image.  We already have code supporting a lot of what
        is needed already here, so I suspect this will work well, but what
        do you think?

Routines to write

Handle GetUndoIcon(QDIconRecord	**editIconH);
& all other stuff having to do with undo */
/*
    Foundation Icon Editor

	Mark T. Collins  19/7/92 18:07
    Editing Functions based on code by Paul Elseth
*/
#pragma noroot
#pragma lint        3
#pragma memorymodel 0
#pragma optimize    14

#include <foundation.h>
#include <event.h>
#include <textedit.h>
#include <window.h>

#define	 FOR_SELECTOR	 (1 << 10)
#define  MenuBarHite     13          /* height of system menu bar */
#define  WTitleHite      12          /* height of standard window title bar */
#define  ScrollBarHeight 13          /* height of standard scrollbar */
#define  ScrollBarWidth	 26          /* width of standard scrollbar */


Pattern		gBlackPattern ={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
							0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
							0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
							0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Pattern		gGrayPattern = {0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
							0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
							0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
							0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc};
Pattern		gRedPattern = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
							0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
							0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
							0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44};

struct {
	QDIconRecord	**iconH;		/* the live resource */
    QDIconRecord	**editIconH;    /* the copy being edited */
    Handle      	UndoH;	        /* picture of icon for undo */
	GrafPort		**imageCache;	/* offscreen image image */
	GrafPort		**maskCache;	/* offscreen mask image */
	Boolean			dirty;			/* dirty */
    Rect			fatIRect;		/* fatbits image rect */
    Rect			fatMRect;		/* fatbits mask rect */
    Rect			sizeRect;		/* resize box rect */
    Rect            toolRect;       /* rect containing tool pseudocontrol */
    Rect            colorRect;      /* rect containing color pseudocontrol */
    Rect            colorSetRect;   /* rect to check for main color */
    Rect            colorMaskRect;  /* rect to check for mask color */
    Rect            textRect;       /* rect containing ht/width text /*
    Rect            icnRect;        /* rect containing icon image */
    Handle          toolPic;        /* picture of the current tool */
    word            infoHt;         /* Info Bar height */
	word			color;			/* color selected */
    word            maskColor;      /* mask color selected */
	word			tool;			/* tool selected */
    word            hOffset;        /* 1 if 320, 2 if 640 mode */
	long			resID;			/* resource ID of the icon */
	} IconData;
typedef struct IconData IconData *IconDataPtr **IconDataHndl;

struct privateData {
	IconDataHndl    data;
    handle          winTitle;
    handle          winTempH;
};
typedef struct privateData **privateDataHndl;

extern EventRecordPtr fEventPtr;
extern word fUserID;
extern long remHelpID;

word                edResFileID, shResFileID, fdResFileID, OldX, OldY,
                    DestX, DestY;
GrafPort	        *TheImage;
fPrivateDataRec 	PrivPB;
fResDataRec     	DataPB;
fResData2Rec    	Data2PB;
fResNameRec     	NamePB;
fResRefRec      	RefPB;
fResCopyRec			CopyPB;
fResLinkRec			LinkPB;
fResConverterRec	ConvertPB;
fGetFileRec			FilePB;
fColorPaletteRec    ColorPB;
char 	            *htStr = "Height: 000  ";
char                *wdStr = "Width: 000  ";
Rect                infoRect;

void DrawProc(void);
void checkData(privateDataHndl);
privateDataHndl getPrivate(GrafPortPtr);

extern void DrawFatImage(IconData **);
extern void DrawFatMask(IconData **);

word REM_OPEN(fOpenRecPtr p)
{
word            retVal, retErr;
long            sizeH;
Handle	        title, ctlH;
privateDataHndl private;
GrafPortPtr     winP;
IconDataHndl    dataH;
IconDataPtr     dataP;

    if (p->resType != rIcon)
        return resInvalidTypeOrID;

	if (parms->fFlag & FOR_SELECTOR)
		return OpenPicker(parms);

	if (!p->resID || (p->fFlag & (F_OPENSILENT | F_OPENDATA))) {

		DataPB.resType   = rIcon;
		RefPB.resType = rIcon;

		if (p->fFlag & F_OPENDATA)
        	DataPB.resData = p->Data;

        else {
        	DataPB.pCount    = 6;
			DataPB.resID     = 1L;
			DataPB.resFileID = edResFileID;
			retErr = fLoadResource(&DataPB);

        	RefPB.pCount = 3;
			RefPB.resID = 1L;
			RefPB.resFileID = edResFileID;
			retErr = fDetachResource(&RefPB);
		}
        DataPB.pCount = 4;
		DataPB.resID = p->resID;		/* if null, then Add returns ID added */
		DataPB.special = 0;				/* no attributes assigned */
		retErr = fAddResource(&DataPB);
        p->resID = DataPB.resID;		/* this may change so pass it back */

        RefPB.pCount = 2;
		RefPB.resID = DataPB.resID;
		retErr = fReleaseResource(&RefPB);

        if (p->fFlag & F_OPENSILENT)
           	return 0;
	}

    (Handle) private = NewHandle(12L, fUserID, 0x0018, 0L);

    DataPB.pCount = 5;                  /* get and lock our window stuff */
	DataPB.resType = rWindParam1;
	DataPB.resID = 0x00000001L;
	DataPB.special = 0;                 /* load */
	DataPB.resFileID = edResFileID;
	retErr = fSpecialMagic(&DataPB);
    DataPB.special = 1;                 /* lock */
    retErr = fSpecialMagic(&DataPB);

    (**private).winTempH = DataPB.resData;

	title = NewHandle(128L, fUserID, 0x8018, 0L);

	NamePB.pCount = 3;                  /* now ask the shell for a title */
	NamePB.resType = rIcon;
	NamePB.resID = p->resID;
	NamePB.resName = (Pointer) *title;
	retErr = fGetWindowTitle(&NamePB);

    (**private).winTitle = title;

    winP = NewWindow2(*title, 0L, &DrawProc, 0L, 1, DataPB.resData, rWindParam1);
    SetPort(winP);
	PrivPB.pCount = 7;
	(GrafPortPtr) PrivPB.winPtr = winP;
	PrivPB.remTaskMask = 0L;
	PrivPB.remSignature = 0;
	PrivPB.Data = (Handle) private;
    PrivPB.groupSignature = 0x0020;
    PrivPB.resType = rIcon;
    PrivPB.resID = p->resID;
    fAddPrivateData(&PrivPB);
    DataPB.pCount = 3;              /* finally, get the resource we're editing */
	DataPB.resType = rIcon;

	DataPB.resID = p->resID;
	retErr = fLoadResource(&DataPB);

    dataH = (**private).data;
    dataP = *dataH;
	dataP->iconH = DataPB.resData;
    sizeH = GetHandleSize(DataPB.resData);
	dataP->editIconH = NewHandle(sizeH, fUserID, 0x0018, 0L);
    HandToHand(dataP->iconH, dataP->editIconH, sizeH);

    SetupInfoBar(dataP);
    SetWindowSize(dataP->editIconH, winP);

    UndoH = GetUndoIcon(dataP->editIconH);

    SetFrameColor(p->wColorPtr, winP);
	SetInfoDraw(DrawColorBar, winP);
    InitFatIcon(dataH);

    ShowWindow(winP);

    return  0;
}

word REM_CLOSE(fCloseRecPtr p)
{
word            retErr;
handle          txtData;
long            txtLength;
GrafPortPtr     winP;
privateDataHndl private;

	if (p->fFlag & FOR_SELECTOR)
		return ClosePicker(parms);

    winP = (GrafPortPtr) p->windowPtr;
    private = getPrivate(winP);
    CheckData((**private).data);
    CloseWindow(winP);

    RefPB.pCount = 2;
    RefPB.resID = p->resID;
	retErr = fReleaseResource(&RefPB);

    DataPB.pCount = 5;
	DataPB.resType = rWindParam1;
    DataPB.resData = (**private).winTempH;
	DataPB.special = 3;
	DataPB.resFileID = edResFileID;
	retErr = fSpecialMagic(&DataPB);

    DisposeHandle(dataP->iconH);
    DisposeHandle((**private).winTitle);
    DisposeHandle((**private).data);
    DisposeHandle(PrivPB.Data);
    InitCursor();

    return  0;
}

word REM_WRITE(fCloseRecPtr p)
{
handle          txtData;
long            txtLength;
GrafPortPtr     winP;
privateDataHndl private;
word            retErr;

    winP = (GrafPortPtr) p->windowPtr;
    private = getPrivate(winP);
    checkData((**private).data);
    return 0;
}

word REM_EVENT(fEventRecPtr p)
{
word            retErr;
Handle	        title;
privateDataHndl private;
GrafPortPtr     winP;

    winP = (GrafPortPtr) fEventPtr->wmTaskData;



    switch (p->taskCode) {

    case updateEvt:
 	    return UpdateEditor((WindowPtr) fEventPtr->wmTaskData);
	case wInInfo:
        return InEditorInfo(fEventPtr);
	case wInContent:
	    return EditorContent(fEventPtr);
	case wInMenuBar:
		return EditorMenu(fEventPtr);
    case app3Evt:
        private = getPrivate(winP);
        title = (**private).winTitle;
    	NamePB.pCount = 3;
	    NamePB.resType = rIcon;
	    NamePB.resID = p->resID;
	    NamePB.resName = (Pointer) *title;
	    retErr = fGetWindowTitle(&NamePB);
	    (**private).winTitle = title;
        SetWTitle(*title, winP);
        break;
    default:
        break;
    }
    return  0;
}

word REM_ACTIVATE(fActivateRecPtr p)
{
handle          txtData;
GrafPortPtr     winP;
long    txtLength;
privateDataHndl private;

	if (p->fFlag & FOR_SELECTOR)
		return = ActivatePicker(parms);

	if (p->fFlag & F_ACTIVATE)
		p->fFlag |= (F_CLIP + F_CLEAR + F_MENUAPPLY);
    else {
        winP = (GrafPortPtr) fEventPtr->wmTaskData;
        checkData((**private).data);
        InitCursor;
    }
    return  0;
}

word REM_GETLINK(fLinkRecPtr p)
{
    return  0;      /* Icons have no Dependents! */
}

word REM_VIDMODE(fVidModeRecPtr p)
{

GrafPortPtr     winP;
Handle          ctlH;
long            txtLength;
ParamListHndl   winH;
handle          txtData;
privateDataHndl private;

    (pointer) winP = p->windowPtr;
    private = getPrivate(winP);
    CheckWindowSize(winP);
    SetFrameColor(p->wColorPtr, p->windowPtr);

    return  0;
}


word REM_PRINT(fCloseRecPtr p)
{
    return  0;  /* no printing in this version */
}

word REM_STARTUP(fStartStopRecPtr p)
{
    fUserID = p->edUserID;
    edResFileID = p->edResFileID;
    shResFileID = p->shResFileID;
    fdResFileID = p->fdResFileID;
    remHelpID = 1L; /* stuff a rText ID into the editors header help field */

    return  0;
}

word REM_SHUTDOWN(fStartStopRecPtr p)
{
	DisposeAll(fUserID);
    return  0;
}

#pragma databank 1

void DrawProc(void)
{
    DrawEditor();
}

#pragma databank 0

void checkData(privateDataHndl private);
{
int     i, changed;
long    size;
pointer privP;

    privP = deref(private);
    HLock(privP->editIconH);

    if (privP->dirty) {
        size = GetHandleSize(privP->editIconH);
        SetHandleSize(size, privP->iconH);
        HLock(privP->iconH);
        HandToHand(privP->editIconH, privP->iconH, size);

        RefPB.pCount = 2;
        RefPB.resType = rIcon;
        RefPB.resID = resID;
        fWriteResource(&RefPB);
    }
    HUnlock(privP->iconH);
    HUnlock(privP->editIconH);
    HUnlock(private);
}

privateDataHndl getPrivate(GrafPortPtr winP)
{
    PrivPB.pCount = 4;
    (GrafPortPtr) PrivPB.winPtr = winP;
    fGetPrivateData(&PrivPB);
    return (privateDataHndl) PrivPB.Data;
}

void CalcFat(IconData** dataH, word hOffset)
{
    IconData		*dataP;
	QDIconRecord	*iconP;
    word	         width, height,x;
	
	dataP = *dataH;
	iconP = *(dataP->editIconH);

	width = (unsigned short) iconP->iconWidth * (7 * hOffset);
    height = (unsigned short) iconP->iconHeight * 7;

	dataP->fatIRect.v1 = 8;
    dataP->fatIRect.h1 = 8 * hOffset;
	dataP->fatIRect.v2 = 8 + height;
    dataP->fatIRect.h2 = 16 + width;

    dataP->fatMRect.v1 = 8;
    dataP->fatMRect.v2 = 8 + height;
    dataP->fatMRect.h1 = width + (16 * hOffset);
    dataP->fatMRect.h2 = width + width + (16 * hOffset);

	dataP->sizeRect.v1 = dataP->fatIRect.v2 - 1;
    dataP->sizeRect.v2 = dataP->sizeRect.v1 + 5;
	dataP->sizeRect.h1 = dataP->fatIRect.h2 - hOffset;
	dataP->sizeRect.h2 = dataP->sizeRect.h1 + (5 * hOffset);

	SetDataSize(dataP->fatMRect.h2 + (hOffset * 2), dataP->fatIRect.v2 + 2, GetPort());
}

void GetPixelRect(word x, word y, Rect *r, word hOffset)
{
	r->h1 = x * (hOffset * 4);
    r->h2 = r->h1 + (hOffset * 3);
	r->v1 = y * 4;
    r->v2 = r->v1 + 3;
}

void Pt2Pixel(word ox, word oy, IconData **dataH, word inMask, word *x, word *y)
{
	IconData	*dataP;
	word		h, v;
	Rect		r;

	dataP = *dataH;
    h = inMask ? dataP->fatMRect.h1 : dataP->fatIRect.h1;
    v = inMask ? dataP->fatMRect.v1 : dataP->fatIRect.v1;

	*x = (ox - h - 4) / 8;
	*y = (oy - v - 2) / 4;
}

word GetPixelColor(word x, word y, QDIconRecord *iconP, word inMask)
{
	char	*p;
	word	color;

	p = (char *) &iconP->iconImage + (iconP->iconWidth * y + x) / 2;
	if (inMask)
	    p += iconP->iconSize;

	asm {
		lda	x
	    lsr	a
        lda	[p]
        bcs	useLo
		and	#0x00f0
        pha
	    lsr	a
	    lsr	a
	    lsr	a
	    lsr	a
		ora	1,s
	    plx
		sta	color
		bra	skip

useLo:	and	#0x000f
		pha
		asl	a
		asl	a
		asl	a
		asl	a
		ora	1,s
	    plx
		sta	color

skip:	
		}

	return color;
}

word PickColor(word ox, word oy, IconData **dataH, word inMask)
{
	word	x, y;

	Pt2Pixel(ox, oy, dataH, inMask, &x, &y);
    return GetPixelColor(x, y, *(**dataH).editIconH, inMask);
}

word GetColor(word color, word ox, word oy, IconData **dataH, word inMask)
{                      
	word	x, y, curColor, oldColor;

	Pt2Pixel(ox, oy, dataH, inMask, &x, &y);

    curColor = GetPixelColor(x, y, *(**dataH).iconH, inMask);
	oldColor = GetPixelColor(x, y, *(**dataH).oldIconH, inMask);

    return (color == curColor) ? oldColor : color;
}

void SetPixelColor(word x, word y, word color, QDIconRecord *iconP, word inMask)
{
	char	*p;

	p = (char *) &iconP->iconImage + (iconP->iconWidth * y + x) / 2;

	asm {
		lda	x
	    lsr	a
		lda	#0x000f
	    bcs	useLo
		lda	#0x00f0
useLo:	tax
		and	color
	    pha
		txa
		eor	#0xffff
		and	[p]
		ora	1,s
        sta	[p]
        plx
	    }
}

void DoBit(word ox, word oy, word color, word inMask, IconData *dataP)
{
	GrafPort		*oPort, **cacheH;
    QDIconRecord	*iconP;
	unsigned short	x, y;
    Rect			baseRect, r;
    Pattern			colorPat;

	iconP = *(dataP->iconH);
	baseRect = inMask ? dataP->fatMRect : dataP->fatIRect;

    if (ox < baseRect.h1 + 4)
		return;
	x = (ox - baseRect.h1 - 4) / 8;
	if (x >= iconP->iconWidth)
	    return;

	if (oy < baseRect.v1 + 2)
	    return;
	y = (oy - baseRect.v1 - 2) / 4;
	if (y >= iconP->iconHeight)
	    return;

	if (x == OldX && y == OldY)
	    return;

	OldX = x;
    OldY = y;

	GetPixelRect(x, y, &r, dataP->hOffset);

	MakePattern(color, colorPat);

/* update the cache: */
	oPort = GetPort();

    cacheH = inMask ? dataP->maskCache : dataP->imageCache;
    HLock((Handle) cacheH);
    SetPort(*cacheH);

	FillRect(&r, colorPat);

    SetPort(oPort);
	HUnlock((Handle) cacheH);

/* update the fatbits window: */
	OffsetRect(&r, (inMask ? dataP->fatMRect.h1 : dataP->fatIRect.h1) + 4,
			    dataP->fatIRect.v1 + 2);

	FillRect(&r, colorPat);

/* update the icon itself: */
	SetPixelColor(x, y, color, iconP, inMask);
}

word ResizeIt(IconData **dataH, word newWd, word newHt)
{
	QDIconRecord	**iconH, *iconP, **tempIconH, *tempIconP;
    char			*p0, *p1, *p2, *p3;
    long			hSize;
    word            newSize, oldSize, oldWd, oldHt, x, y, err;

    iconH = (**dataH).editIconH;

    hSize = GetHandleSize(iconH);
	err = GetNewHandle(hSize, (Handle *) &tempIconH);
	if (err != 0)
		return err;
	HandToHand((Handle) iconH, (Handle) tempIconH, hSize);

    tempIconP = *tempIconH;

	newSize = ((newWd / **dataH).hOffset) * newHt;

    SetHandleSize((long) newSize * 2 + sizeof(Word) * 4, (Handle) iconH);
	err = toolerror();
    if (err != 0)
	    return err;

	iconP = *iconH;

/* put in new size info for icon (saving old): */
	oldSize = iconP->iconSize;
	oldHt = iconP->iconHeight;
	oldWd = iconP->iconWidth;
	iconP->iconSize = newSize;
	iconP->iconHeight = newHt;
	iconP->iconWidth = newWd;

/* zero the new image and mask: */
	p0 = (char *) &iconP->iconImage;
    p2 = p0 + newSize;
    asm {	
		ldy	newSize
        ldx	#0xffff
        sep	#0x20
		dey
zLoop:	txa
		sta	[p0],y
        inc	a
        sta	[p2],y
		dey
	    bpl	zLoop
        rep	#0x20
		}

/* copy resized image back in: */
	y = newHt < oldHt ? newHt : oldHt;
	while (--y >= 0) {
		p0 = (char *) &tempIconP->iconImage + y * (oldWd / 2);
        p2 = p0 + oldSize;

        p1 = (char *) &iconP->iconImage + y * (newWd / 2);
        p3 = p1 + newSize;
		
		x = newWd < oldWd ? newWd : oldWd;

        asm {
			lda	x
            lsr	a
			tay
			dey
            sep	#0x20
cLoop2:		lda [p0],y
			sta	[p1],y
            lda	[p2],y
	        sta	[p3],y
			dey
			bpl	cLoop2
			rep	#0x20
            }
		}

	DisposeHandle((Handle) tempIconH);

	return 0;
}

void GrowFat(IconData **dataH, Point pt)
{
	IconData		*dataP;
	GrafPort		*oPort;
	QDIconRecord	*iconP, **iconH;
	Rect			limits, slop;
	long			newSize;
    word			newHt, newWd, h, v, err;
    
	dataP = *dataH;

    h = dataP->fatIRect.h1 - dataP->fatIRect.h2;
    v = dataP->fatIRect.v1 - dataP->fatIRect.v2;
						
	limits.h1 = (4 * 4) * 2 + 4 + h;
	limits.v1 = (4 * 4) + 2 + v;

    limits.h2 = (4 * 320) * 2 + 4 + h;
    limits.v2 = (4 * 100) + 2 + v;

/* use the window manager's portRect for the slop rect: */
    oPort = GetPort();
	SetPort(GetWMgrPort());
    GetPortRect(&slop);
    SetPort(oPort);

/* interact: */
	(Point) newSize = DragRect(nil, gGrayPattern, pt, &dataP->fatIRect, &limits, &slop, 0x0014);
	asm {
		lda	newSize
		sta	newHt
        lda	newSize+2
        sta	newWd
	    }
	newHt = (newHt + dataP->fatIRect.v2 - dataP->fatIRect.v1 - 2) / 4;
	newWd = (newWd + dataP->fatIRect.h2 - dataP->fatIRect.h1 - 4) / 8;
	newWd = (newWd + 1) & 0xfffe;

	iconH = dataP->iconH;
    iconP = *iconH;

    if (newHt != iconP->iconHeight || newWd != iconP->iconWidth) {
		CopyUndoIcon(dataH);  /* needs rework to support picture vs icon image */
		err = ResizeIt(dataH, newWd, newHt);
/*  here's where we need to resize the info bar if necessary */
	    if (err != 0)
	        SysError(err);
		RedrawFat(dataH);
	    }
}

void FatClick(EventRecord *event)
{
	IconData	*dataP, **dataH;
	GrafPort	*oPort;
	WindowPtr	wp;
	Point		pt;
	word		x, y, color, tool, inImage, inMask;

	oPort = GetPort();
    wp = (WindowPtr) event->wmTaskData;

	dataH = (IconData **) getPrivate(wp);
	HLock((Handle) dataH);
    dataP = *dataH;
	tool = dataP->tool;

	pt = event->where;

	StartDrawing(wp);
    GlobalToLocal(&pt);

	inImage = PtInRect(&pt, &dataP->fatIRect);
	inMask = PtInRect(&pt, &dataP->fatMRect);
	if (inImage || inMask) {
		switch (tool) {
	        case kPickerTool:						/* pick color */
		        color = PickColor(pt.h, pt.v, dataH, inMask);
	            if (inMask)
					color ^= 0x00ff;
				dataP->color = color;
				UpdateColor(dataH, color);
				CopyOldIcon(dataH);   /* this should perhaps be reworked */
				break;                /* to simply restore org icn image */
			case kBucketTool:						/* fill */
				FillIcon(dataH, pt);
				break;
			case kShifterTool:						/* shift */
				ShiftIcon(dataH, pt);
		        break;
	    	case kPencilTool:						/* draw */
				CopyUndoIcon(dataH);  /* needs rework to support pic vs icon */
	            OldX = OldY = -1;     /* image support */

				color = GetColor(dataP->color, pt.h, pt.v, dataH, inMask);

	            do {
					DoBit(pt.h, pt.v, color, inMask, dataP);

	                GetMouse(&pt);
		            } while (StillDown(0));

				if (inMask)
		            EraseEm(dataH);
				DrawEm(dataH);
                (**dataH).dirty = true;
	            break;
			}
	    }    
	else if (PtInRect(&pt, &dataP->sizeRect)) {
		GrowFat(dataH, pt);
        (**dataH).dirty = true;
	    }

    SetOrigin(0, 0);
	HUnlock((Handle) dataH);
	SetPort(oPort);
}


 /*
  *	RedrawFat2()
  *		Re-cache the fatbits data.
  */
void RedrawFat2(IconData **dataH)
{
	IconData	*dataP;
    word		width, height;

	CalcFat(dataH);

    dataP = *dataH;

	width = dataP->fatIRect.h2 - (dataP->fatIRect.h1 - (4 * dataP->hOffset));
	height = dataP->fatIRect.v2 - dataP->fatIRect.v1 - 4;

    AdjustOffPort(dataP->imageCache, width, height);
    AdjustOffPort((**dataH).maskCache, width, height);

	DrawFatImage(dataH);
	DrawFatMask(dataH);
}
    

 /*
  *	RedrawFat()
  *		Redraw the fatbits window.
  */
void RedrawFat(IconData **dataH)
{
	Rect		r;

	HideControl((**dataH).control);
	GetPortRect(&r);
	InvalRect(&r);
	EraseRect(&r);

    RedrawFat2(dataH);
}

/*
 *	CopyUndoIcon()
 *		Copy current icon to the "undo" icon.
        This needs to be redone to allow for handling of undo based on a
        picture rather than an icon image.  Left in for reference purposes!
word CopyUndoIcon(IconData **dataH)
{
	IconData		*dataP;
	QDIconRecord	**iconH, **undoH;
	long			size;
	word			err;

    dataP = *dataH;
    iconH = dataP->iconH;
    undoH = dataP->undoIconH;

    size = GetHandleSize((Handle) iconH);
	SetHandleSize(size, (Handle) undoH);
    err = toolerror();
	if (err == 0) {
		HandToHand(iconH, undoH, size);
		err = toolerror();
		if (err == 0)
			EnableUndo();
	    }

	return err;
}
*/

/*
 *	CopyOldIcon()
 *		Copy current icon to the "old" icon.
        This might be easier...  we shall see
 */
short CopyOldIcon(IconData **dataH)
{
	IconData		*dataP;
	QDIconRecord	**iconH, **oldH;
	long			size;
	short			err;

    dataP = *dataH;
    iconH = dataP->editIconH;
    oldH = dataP->iconH;

    size = GetHandleSize((Handle) iconH);
	SetHandleSize(size, (Handle) oldH);
    err = toolerror();
	if (err == 0) {
		HandToHand(iconH, oldH, size);
		err = toolerror();
        }

	return err;
}


/*
 *	EnableUndo()
 *		Enable the undo menu item.
 */
void EnableUndo(void)
{
/* this needs to reset the flags to allow an undo hit - set when the undo
   is set up */
}

void ShiftDraw2(word x, word y, GrafPort *image)
{
	x += DestX + 4;
	y = (y & 0xfffc) + DestY + 2;
	PPToPort(&image->portInfo, &image->portRect, x, y, notXOR);
}   

#pragma databank	1
#pragma toolparms	1
/*
 *	ShiftDraw()
 *		Draw the fat image being dragged.
 */
static
void ShiftDraw(word deltaY, word deltaX, word parm)
{
	static word	    L00C0, L60B4;
    word            x, y;

	x = L00C0;
	if (parm & 1)
		++x;
	L60B4 = x & 1;

	if (parm & 1)
	    if ((L00C0 & 1) != L60B4) {
			++L00C0;
			ShiftDraw2(deltaX, deltaY, TheImage);
	        }
}
#pragma databank	0
#pragma toolparms	0


/*
 *	ShiftIt()
 *		Shift the icon image & mask according to deltaX, deltaY.
 */
static
void ShiftIt(IconData **dataH, word deltaX, word deltaY)
{
	word	iSize, iHeight, iWidth, iWBytes, sLine, dLine;
	QDIconRecord	*iconP;
	char			*ptr0, *ptr1, *ptr2, *ptr3;

    iconP = *((**dataH).editIconH);

	iSize = iconP->iconSize;
	iHeight = iconP->iconHeight;
	iWidth = iconP->iconWidth;
	iWBytes = (iWidth - 1) / 2 + 1;

/* move each line, shifting it into place: */
	if (deltaY < 0) {
		dLine = 0;
		sLine = -deltaY;
        if (sLine >= iHeight)
	        return;
	    }
	else {
		dLine = iHeight - 1;
        sLine = dLine - deltaY;
        if (sLine < 0)
	        return;
		}

	do {
	    ptr0 = (char *) &iconP->iconImage + (sLine * (iWidth / 2));
		ptr2 = ptr0 + iSize;

	    ptr1 = (char *) &iconP->iconImage + (dLine * (iWidth / 2));
		ptr3 = ptr1 + iSize;

		asm {
			ldx	sLine
            bmi	clrRow
            cpx	iHeight
	        bcs	clrRow

			lda	deltaX		    /* first shift the row horizontally */
			beq	noShift
			bpl	goRight
			eor	#0xffff
/*			inc	a			*/
			pha
            tax
			sep	#0x20
shlLoop1:	ldy	iWBytes
			dey
			sec
loop1:		lda	[ptr0],y
			rol	a
			sta	[ptr0],y
			dey
			bpl	loop1
			dex
	        bne	shlLoop1

			plx					/* shift the mask left X bits */
shlLoop2:	ldy	iWBytes
		    dey
	        clc
loop2:		lda	[ptr2],y
			rol	a
			sta	[ptr2],y
            dey
            bpl	loop2
			dex
            bne	shlLoop2
            bra	noShift

goRight:	ldx	deltaX		    /* shift the image right X bits */
			sep	#0x20
shrLoop1:	phx
			ldy	#0
			ldx	iWBytes
	        sec
loop3:	    lda	[ptr0],y
			ror	a
            sta	[ptr0],y
	        iny
            dex
	        bne	loop3
			plx
	        dex
	        bne	shrLoop1

	        ldx	deltaX			/* shift the mask right X bits */
shrLoop2:	phx
			ldy	#0
            ldx	iWBytes
	        clc
loop4:		lda	[ptr2],y
			ror	a
	        sta	[ptr2],y
	        iny
            dex
	        bne	loop4
            plx
            dex
	        bne	shrLoop2
            bra	noShift

clrRow:		sep	#0x20
			ldy	iWBytes		    /* clear remaining rows */
			dey
            ldx	#0xffff
clrLoop:	txa
			sta	[ptr1],y
            inc	a
			sta	[ptr3],y
            dey
			bpl	clrLoop
			bra	cleared

noShift:	sep	#0x20
			ldy	iWBytes			/* now copy the newly shifted row into it's new place */
			dey
cLoop:		lda	[ptr0],y
			sta	[ptr1],y
            lda	[ptr2],y
            sta	[ptr3],y
            dey
            bpl	cLoop

cleared:	rep	#0x20
			}

		} while (deltaY < 0 ? (++sLine, ++dLine < iHeight) : (--sLine, --dLine >= 0));
}


/*
 *	ShiftIcon()
 *		Interactively shift the icon image and mask.
 */
static
void ShiftIcon(IconData **dataH, Point pt)
{
	Rect		dragRect, r;
	IconData	*dataP;
	Region		**oClip;
	GrafPort	**image;
    long		result;
    word		deltaX, deltaY;

    dataP = *dataH;

	dragRect = r = dataP->fatIRect;

	DestX = r.h1;
    DestY = r.v1;
    image = dataP->imageCache;
	HLock((Handle) image);
	TheImage = *image;

	InsetRect(&r, r.h1 - r.h2, r.v1 - r.v2);
	InsetRect(&dragRect, 2, 2);

    oClip = NewRgn();				/* clip to the drag rect */
	GetClip(oClip);
    ClipRect(&dragRect);

    EraseRect(&dragRect);			/* erase the image first */

    (Point) result = DragRect(ShiftDraw, gGrayPattern, pt, &dragRect, &r, &r, 0x0888);
	asm {
		lda	result
		sta	deltaY
		lda	result+2
		sta	deltaX
	    }

	ShiftDraw2(deltaX, deltaY, TheImage);	/* redraw the icon image */
	HUnlock((Handle) image);
	SetClip(oClip);					/* restore the original clip rgn */

    deltaX = deltaX >= 0 ? deltaX / 2 : deltaX / 2 - 1;
	deltaY = deltaY >= 0 ? deltaY / 4 : deltaY / 4 - 1;

    if (deltaX != 0 || deltaY != 0) {
		CopyUndoIcon(dataH);    /* will need rework to support pic support */
		ShiftIt(dataH, deltaX, deltaY);
        (**dataH).dirty = true;
		RedrawFatbits(dataH, true);
		DrawFatImage(dataH);
		}
}

/*
 *	InitFatIcon()
 *		Initialize the fat icon data record.
 */
static
void InitFatIcon(IconData **dataH)
{
    IconData		*dataP;
    FontInfoRecord	fi;
	GrafPort		**imageH, **maskH;
    Handle			uh, oh;
	word			width, height, err;

    uh = NewHandle(10L, fUserID, 0x0018, 0L);
    uh = NewHandle(10L, fUserID, 0x0018, 0L);

    dataP = *dataH;
	dataP->dirty = false;
	dataP->imageCache = nil;
	dataP->maskCache = nil;
	dataP->color = 0;
	dataP->tool = 0;

	CalcFat(dataH, dataP->vOffset);

/* allocate the offscreen pixelmaps: */
    dataP = *dataH;
	width = dataP->fatIRect.h2 - dataP->fatIRect.h1 - 8;
	height = dataP->fatIRect.v2 - dataP->fatIRect.v1 - 4;

	err = CopyUndoIcon(dataH);   /* may need work to support pic support */
	err = CopyOldIcon(dataH);

	err = CreateOffPort(width, height, &imageH);
	if (err == 0) {
		err = CreateOffPort(width, height, &maskH);
		if (err == 0) {
    		dataP = *dataH;
		    dataP->imageCache = imageH;
		    dataP->maskCache = maskH;

  			DrawFatImage(dataH);
			DrawFatMask(dataH);
			}
		else
			DisposeOffscreen(imageH);
		}
}

static
void SetWindowSize(QDIconRecord **iconH, WindowPtr wp)
{
	QDIconRecord	*iconP;
    word            xyzzy, minWidth, height, width, maxWidth, qdSCB, hOffset;
	Rect			wRect;

	iconP = *iconH;

/* calc window top and bottom:- note change for new content concept */
    xyzzy = MenuBarHeight + WTitleHeight +
                    ((iconP->iconHeight > 16 ? iconP->iconHeight : 16) + 4);


	height = (iconP->iconHeight * 4) + 6;
    if (height > 200 - xyzzy - kScrollBarHeight)
		height = 200 - xyzzy - kScrollBarHeight;

	wRect.v1 = ((200 - xyzzy - kScrollBarHeight) - height) / 3 + xyzzy;
	wRect.v2 = wRect.v1 + height;

/* calc left and right: */

    qdSCB = GetMasterSCB();
    qdSCB ^= 0x80;
    hOffset = (qdSCB & 0x80) ? 2 : 1;
    maxWidth = (319 * hOffset) - kScrollBarWidth;
	width = iconP->iconWidth * 20 + 88;
    minWidth = (26 * hOffset) + 84 + iconP->iconWidth;
	if (width < minWidth)
	    width = minWidth;
	if (width > maxWidth)
	    width = maxWidth;

	wRect.h1 = ((maxWidth - width) / 2 + 2) & 0xfffe;
    wRect.h2 = (wRect.h1 + width) & 0xfffe;

/* set window size: */
	ResizeWindow(false, &wRect, wp);
}
      
/*
 *	DrawEm()
 *		Draw the icon in different states.
        We should use something like this to draw our icon mode window
        here for reference
 */
void DrawEm(IconData **dataH)
{
	short			x, y;
	QDIconRecord	*iconP, **iconH;
    short			oState;

    iconH = (**dataH).iconH;
	oState = HGetState((Handle) iconH);
	HLock((Handle) iconH);
	iconP = *iconH;

	x = (**dataH).fatMRect.h2 + 16;
    y = (**dataH).fatMRect.v1 + 4;

    DrawIcon(iconP, 0, x, y);
    DrawIcon(iconP, 1, x + 4 + iconP->iconWidth * 2, y);
    DrawIcon(iconP, 2, x, y + 8 + iconP->iconHeight);
    DrawIcon(iconP, 4, x + 4 + iconP->iconWidth * 2, y + 8 + iconP->iconHeight);

	HSetState((Handle) iconH, oState);
}

void MakePattern(short color, Pattern pat)
{
	asm {
        lda	color
	    xba
		ora	color
        ldy	#0x001e
loop:	sta	[pat],y
		dey
	    dey
		bpl	loop
		}
}

/*
 *	RedrawFatbits()
 *		Redraw the fatbits image or mask.
 */
void RedrawFatbits(IconData **dataH, word mask)
{
    GrafPort	*oPort;
    Cursor		*oCurs;
	IconData	*dataP;
    Rect		r;

    oCurs = GetCursorAdr();
	SetWaitCursor();
	oPort = GetPort();
    StartDrawing(FrontWindow());

    dataP = *dataH;
    r = mask ? dataP->fatMRect : dataP->fatIRect;
	InsetRect(&r, 2, 1);
	InvalRect(&r);

    if (mask) {
		DrawFatMask(dataH);
/*		EraseEm(dataH);         These two routines are not needed since */
/*      UpdateEm(dataH);        we present the different modes differently */
        }
    else
  		DrawFatImage(dataH);

	SetOrigin(0, 0);
    SetPort(oPort);
	SetMyCursor(oCurs);
}


/*
 *	PaintImage()
 *		Paint cached icon image or mask to the port.
 */
void PaintImage(GrafPort **src, word x, word y)
{
	HLock((Handle) src);
	PPToPort(&(**src).portInfo, &(**src).portRect, x, y, modeCopy);
	HUnlock((Handle) src);
}

/*
 *	DrawEditor()
 *		Draw an icon editor window.
 */
#pragma	databank	1
static
pascal void DrawEditor(void)
{		
	IconData		*dataP, **dataH;
   	QDIconRecord	**iconH, *iconP;
    WindowPtr		wp;

    wp = GetPort();

	dataH = (IconData **) getPrivate(wp);
	HLock((Handle) dataH);
	dataP = *dataH;
    iconH = dataP->editIconH;

	SetPenSize(2, 1);
    FrameRect(&dataP->fatIRect);
    FrameRect(&dataP->fatMRect);
	FrameRect(&dataP->sizeRect);

	PenNormal();

/* draw the fat icon image: */
	PaintImage(dataP->imageCache, dataP->fatIRect.h1 + 4, dataP->fatIRect.v1 + 2);

/* draw the fat icon mask: */
	PaintImage(dataP->maskCache, dataP->fatMRect.h1 + 4, dataP->fatMRect.v1 + 2);
}
#pragma	databank	0


/*
 *	UpdateEditor()
 *		Update an icon editor window.
 */
static
short UpdateEditor(WindowPtr wp)
{
	BeginUpdate(wp);
    EndUpdate(wp);

	return -1;
}


word InEditorInfo(EventRecord *event)
{
GrafPortPtr     oldP, winP, showP;
word            qdSCB, hOffset, iconHt, i;
QDIconRecord    *IconP;    /* the copy being edited */
            dataH, dataP;

    oldP = GetPort();
    winP = (WindowPtr) event->wmTaskData;

    qdSCB = GetMasterSCB();
    qdSCB ^= 0x80;
    hOffset = (qdSCB & 0x80) ? 2 : 1;

	dataH = (IconData **) getPrivate(wp);
	HLock((Handle) dataH);
    dataP = *dataH;
    iconP = *(dataP->editIconH);
	pt = event->where;

	StartInfoDrawing(infoRect, wp);
    GlobalToLocal(&pt);

	if (PtInRect(&pt, &dataP->toolRect) {
        EndInfoDrawing();
        /* handle tool selection */
    };
	else if (PtInRect(&pt, &dataP->colorSetRect) {
        EndInfoDrawing();
        /* handle color selection */
    };
	else if (PtInRect(&pt, &dataP->colorMaskRect) {
        EndInfoDrawing();
        /* handle mask color selection */
    };
	else if (PtInRect(&pt, &dataP->icnRect) {
        EndInfoDrawing();

        DataPB.pCount = 5;                  /* get and lock our window stuff */
	    DataPB.resType = rWindParam1;
	    DataPB.resID = 0x00000001L;
	    DataPB.special = 0;                 /* load */
	    DataPB.resFileID = edResFileID;
	    retErr = fSpecialMagic(&DataPB);
        DataPB.special = 1;                 /* lock */
        retErr = fSpecialMagic(&DataPB);
        showP = NewWindow2(*title, 0L, 0L, 0L, 1, DataPB.resData, rWindParam1);
        SetPort(winP);

        iconP->iconHeight;
        SizeWindow(iconP->iconWidth + (hOffset * 2), ((iconP->iconHeight + 1) * 4) + 1, showP);
        ShowWindow(showP);

        DrawIcon(dataP->editIconH, 0, iconP->iconHeight + 1);
        DrawIcon(dataP->editIconH, 1, (iconP->iconHeight + 1) * 2);
        DrawIcon(dataP->editIconH, 2, (iconP->iconHeight + 1) * 3);
        DrawIcon(dataP->editIconH, 4, (iconP->iconHeight + 1) * 4);

        do {
        } until (StillDown(0) == False);    /* Marc's not gonna like this ! */
        CloseWindow(showP);

    };
    else EndInfoDrawing();

	return 0;
}

word EditorContent(EventRecord *event)
{
	FatClick(event);
	return 0;
}

/*
 *	EditorMenu()
 *		Menu item selected.
 */
word EditorMenu(EventRecord *event)
{
	WindowPtr	wp;
    IconData	**dataH;
	
    wp = FrontWindow();
	dataH = (IconData **) getPrivate(wp);
    
    switch ((short) event->wmTaskData) {
	    case 0x8001:					/* colored mask */
	        break;
	    case 0x8002:					/* create mask */
			MakeMask(dataH);
	        break;
	    case 0x8003:					/* copy icon to mask */
	        break;
	    }
	
	return 0;
}


/*
 *	UpdateCursor()
 *		Update the cursor image.
 */
void UpdateCursor(Point pt, word modifiers)
{
	GrafPort	*oPort;
	WindowPtr	wp;
	IconData	**dataH;
	
    wp = FrontWindow();
	dataH = (IconData **) getPrivate(wp);

    oPort = GetPort();
	SetPort(wp);
	GlobalToLocal(&pt);

    if (PtInRect(&pt, &(**dataH).fatIRect) ||
    	PtInRect(&pt, &(**dataH).fatMRect)) {
#if	0
		if (modifiers & shiftKey)
			SetMyCursor(&ShifterCursor);
        else if (modifiers &optionKey)
			SetMyCursor(&BucketCursor);
        else
			SetMyCursor(&PencilCursor);
#else
		switch ((**dataH).tool) {
			case kPencilTool:
	            SetMyCursor(&PencilCursor);
                break;
			case kBucketTool:
	            SetMyCursor(&BucketCursor);
                break;
			case kShifterTool:
	            SetMyCursor(&ShifterCursor);
                break;
			case kPickerTool:
				SetMyCursor(&PickerCursor);
            	break;
	        default:
	    		SetArrowCursor();
	        }      
#endif
		}
	else
	    SetArrowCursor();

	SetPort(oPort);
}

/*
 *	FillSource()
 *		Create the source grafPort/locInfo for MakeMask() and FillIcon().
 */
word FillSource(GrafPort *tempPort, QDIconRecord **iconH)
{
	word        w, h, rowBytes, err;
	LocInfo		portInfo;

    w = (**iconH).iconWidth;
	h = (**iconH).iconHeight;

	w = (w * 2 + 7) & 0xfff8;

    rowBytes = (w / 4 + 7) & 0xfff8;
    portInfo.boundsRect.h1 = 0;
/*	portInfo.boundsRect.h2 = (x + 1) & 0xfffe;	*/
	portInfo.boundsRect.h2 = rowBytes * 4;
    portInfo.boundsRect.v1 = 0;
    portInfo.boundsRect.v2 = h;
    portInfo.width = rowBytes;

	err = GetNewPtr(h * rowBytes, &portInfo.ptrToPixImage);
	if (err == 0) {
		OpenPort(tempPort);
		portInfo.portSCB = GetMasterSCB();
		SetPortLoc(&portInfo);
		SetPortRect(&portInfo.boundsRect);
		EraseRect(&portInfo.boundsRect);
		}

	return err;
}


/*
 *	DisposeSource()
 *		Dispose of the temporary grafPort.
 */
void DisposeSource(GrafPort *port)
{
	ClosePort(port);
	DisposeIfPtr(port->portInfo.ptrToPixImage);
}


/*
 *	Icon2Pixmap()
 *		Copy icon record into a pixel map.
 */
static
void Icon2Pixmap(QDIconRecord **iconH, GrafPort *port)
{
	QDIconRecord	*iconP;
    char			*pixmap, *image;
	unsigned int	rowBytes, h, w;

	iconP = *iconH;
	w = iconP->iconWidth;
	h = iconP->iconHeight;
	image = (char *) &iconP->iconImage;

	rowBytes = port->portInfo.width;
	pixmap = port->portInfo.ptrToPixImage;

	asm {
	    ldx	h
vLoop:  lda	w
		dec	a
		lsr	a
		tay
		inc	a
	    pha
		sep	#0x20
hLoop:  lda	[image],y
		sta	[pixmap],y
		dey
		bpl	hLoop
	    rep	#0x20
		pla
        clc
        adc	image
        sta	image
        bcc	noInc1
        inc	image+2
noInc1:	clc
		lda	pixmap
        adc	rowBytes
		sta	pixmap
	    bcc	noInc2
        inc	pixmap+2
noInc2: dex
		bne	vLoop
		}
}


/*
 *	Pixmap2Icon()
 *		Copy a pixel map into an icon record.
 */
static
void Pixmap2Icon(GrafPort *port, QDIconRecord **iconH, Boolean mask)
{
	QDIconRecord	*iconP;
    char			*pixmap, *image;
	unsigned int	rowBytes, h, w;
    short			invFlag;

	iconP = *iconH;
	w = iconP->iconWidth;
	h = iconP->iconHeight;
	image = (char *) &iconP->iconImage;
    if (mask) {
		image += iconP->iconSize;
	    invFlag = 0xffff;
	    }
    else
    	invFlag = 0x0000;

	rowBytes = port->portInfo.width;
	pixmap = port->portInfo.ptrToPixImage;

	asm {
	    ldx	h
vLoop:  lda	w
		dec	a
		lsr	a
		tay
		inc	a
	    pha
		sep	#0x20
hLoop:  lda	[pixmap],y
		eor	invFlag
		sta	[image],y
		dey
		bpl	hLoop
	    rep	#0x20
		pla
        clc
        adc	image
        sta	image
        bcc	noInc1
        inc	image+2
noInc1:	clc
		lda	pixmap
        adc	rowBytes
		sta	pixmap
	    bcc	noInc2
        inc	pixmap+2
noInc2: dex
		bne	vLoop
		}
}


/*
 *	FillIcon()
 *		Fill an area in the icon.
 */
void FillIcon(IconData **dataH, Point pt)
{
	GrafPort		tempPort, *oPort;
    QDIconRecord	**iconH;
    Cursor			*oCurs;
	Rect			r;
	Pattern			patt;
    word			leakTable[2];
    word			x, y, err;

	
    oCurs = GetCursorAdr();
	SetWaitCursor();
    oPort = GetPort();

    CopyUndoIcon(dataH);
    iconH = (**dataH).iconH;
    
	leakTable[0] = 1;
    leakTable[1] = PickColor(pt.h, pt.v, dataH, false);
	Pt2Pixel(pt.h, pt.v, dataH, false, &x, &y);

    err = FillSource(&tempPort, iconH);
	if (err == 0) {	
/* make sure the xtra space in the background is _not_ the leak color: */
		MakePattern(leakTable[1] ^ 0x00ff, patt);	
        FillRect(&tempPort.portRect, patt);

        Icon2Pixmap(iconH, &tempPort);	/* copy icon image into the offscreen pixelmap */

        MakePattern((**dataH).color, patt);
        SeedFill(&tempPort.portInfo, &tempPort.portRect,
				 &tempPort.portInfo, &tempPort.portRect, x * 2, y,
				 destModeLeaveMask + resMode640DMask, patt, leakTable);
		err = toolerror();

		Pixmap2Icon(&tempPort, iconH, false);

        DisposeSource(&tempPort);

        SetPort(oPort);

        r = (**dataH).fatIRect;
        InsetRect(&r, 2, 1);
		InvalRect(&r);
        UpdateEm(dataH);
        DrawFatImage(dataH);
        Dirty(dataH);
        }
	else
		SetPort(oPort);

	SetMyCursor(oCurs);

    if (err != 0)
		SysError(err);
}


/*
 *	MakeMask()
 *		Construct a mask for this icon.
 */
void MakeMask(IconData **dataH)
{
	GrafPort		tempPort, *oPort;
	QDIconRecord	**iconH;
    Cursor			*oCurs;
	LocInfo			portInfo;
    word			leakTable[2];
	word			err;

	oCurs = GetCursorAdr();
	SetWaitCursor();
    oPort = GetPort();

    CopyUndoIcon(dataH);
    iconH = (**dataH).iconH;

    err = FillSource(&tempPort, iconH);
    if (err == 0) {
		Icon2Pixmap(iconH, &tempPort);
        
		leakTable[0] = 1;
		leakTable[1] = 0xffff;	/* leak color is white */

		CalcMask(&tempPort.portInfo, &tempPort.portRect,
        		 &tempPort.portInfo, &tempPort.portRect,
       			 destModeClrToOnes + resMode640DMask, 0L, leakTable);
		err = toolerror();

		Pixmap2Icon(&tempPort, iconH, true);

		RedrawFatbits(dataH, true);
		Dirty(dataH);
        }

	DisposeSource(&tempPort);
    SetPort(oPort);
	SetMyCursor(oCurs);

    if (err != 0)
		SysError(err);
}

word GetNewHandle(long size, Handle *h)
{
	*h = NewHandle(size, fUserID, 0, 0L);

    return toolerror();
}


/*
 *	GetNewPtr()
 * 		Allocate a new pointer.
 */

word GetNewPtr(long size, Ptr *p)
{
	*p = *NewHandle(size, fUserID, attrFixed, 0L);

    return toolerror();
}

short DisposePtr(Ptr p)
{
	Handle	h;
    short	err;

    h = FindHandle(p);
    err = toolerror();
	if (err == 0) {
		DisposeHandle(h);
        err = toolerror();
	    }

	return err;
}

word DisposeIfHandle(Handle h)
{
	word	err;

	CheckHandle(h);
	err = toolerror();
	if (err != 0)
		asm {brk 0xff}
	else
		DisposeHandle(h);

	return toolerror();
}

word DisposeIfPtr(Ptr p)
{
	word	err;

	err = DisposePtr(p);
	if (err != 0)
		asm {brk 0xfe}

	return err;
}

word HGetState(Handle h)
{
	word	attrs;

    asm {
		ldy	#4
		lda	[h],y
        sta	attrs
		}

	return attrs;
}

void HSetState(Handle h, word state)
{
    asm {
        lda state
		ldy	#4
		sta	[h],y
		}
}

word AddPixelMap(word width, word height)
{
	LocInfo	locInfo;
    Ptr		pixImagePtr;
	word	err;
	
    locInfo.portSCB = GetMasterSCB();

    locInfo.boundsRect.h1 = 0;
	locInfo.boundsRect.h2 = width;
	locInfo.boundsRect.v1 = 0;
	locInfo.boundsRect.v2 = height;

    locInfo.width = ((width / 4) + 7) & 0xfff8;

	err = GetNewPtr((long) locInfo.width * height, &pixImagePtr);
	if (err == 0) {
		locInfo.ptrToPixImage = pixImagePtr;

		SetPortLoc(&locInfo);

		SetPortRect(&locInfo.boundsRect);

		ClipRect(&locInfo.boundsRect);
        SetVisRgn(GetClipHandle());

		EraseRect(&locInfo.boundsRect);
		}

	return err;
}

word CreateOffPort(word width, word height, GrafPort ***pMapH)
{
	GrafPort	*oPort, **portH;
    word		err;

    oPort = GetPort();

    portH = *pMapH = 0;

/* get memory for the cacheing port: */
	err = GetNewHandle(sizeof(GrafPort), (Handle *) &portH);
    if (err == 0) {
		HLock((Handle) portH);

		OpenPort(*portH);
		err = toolerror();
	    if (err == 0) {
		    err = AddPixelMap(width, height);
            if (err == 0) {
				HUnlock((Handle) portH);
				*pMapH = portH;
				}
			}
        }

	if (err != 0 && portH != nil)
	    DisposeIfHandle((Handle) portH);

	return err;
}

word AdjustOffPort(GrafPort **pMapH, word width, word height)
{
	GrafPort	*oPort, *pMapP;
	LocInfo		locInfo;
	word		err;

	oPort = GetPort();

/* switch to the offscreen port: */
	HLock((Handle) pMapH);
	pMapP = *pMapH;
	SetPort(pMapP);

/* dispose of current pixelmap: */
	DisposeIfPtr((Ptr) pMapP->portInfo.ptrToPixImage);

/* create new pixel map: */
	err = AddPixelMap(width, height);

    SetPort(oPort);
	HUnlock((Handle) pMapH);

    return err;
}

word DisposeOffscreen(GrafPort **pMapH)
{
	DisposeIfPtr((**pMapH).portInfo.ptrToPixImage);
	ClosePort(*pMapH);
    DisposeIfHandle((Handle) pMapH);
}

#pragma databank 1
void DrawInfoBarProc () {

IconData		*dataP, **dataH;
QDIconRecord	**iconH, *iconP;
PatternPtr      oldPat;

	dataH = (IconData **) getPrivate(GetPort());
	HLock((Handle) dataH);
	dataP = *dataH;

    iconH = dataP->editIconH;
    DrawPicture(dataP->toolPic, &(dataP->toolRect));

	SetPenSize(2, 1);
    FrameRect(&colorRect);
	PenNormal();

    oldPat = GetPenPat();
    SetSolidPenPat(dataP->color);
    PaintRect(&colorSetRect);

    SetSolidPenPat(dataP->maskColor);
    PaintRect(&colorMaskRect);

    MoveTo(textRect.h1, textRect.v1 + 8);
    Int2Dec(iconP->iconWidth, &wdStr[7], 3, false);
    DrawCString(wdStr);
    Int2Dec(iconP->iconHeight, &htStr[8], 3, false);
    DrawCString(htStr);
    DrawIcon(*iconH, 0, dataP->icnRect.h1, dataP->icnRect.v1);
}
#pragma	databank	0

void SetupInfoBar(IconDataPtr Data) {

word            err, hOffset, qdSCB;
Rect            destRect;
QDIconRecord	*iconP;

    ColorPB.pCount = 8;
    ColorPB.flag = silent;   /* fill in appropriate- can't remember from here */
    err = remColorPalette(&ColorPB);
    Data->toolPic = ColorPB.pic;

	iconP = (**dataP).editIconH;
    Data->color = 1;
    Data->maskColor = 0;
    Data->tool = 0;
    Data->infoHt = (iconP->iconHeight > 16 ? iconP->iconHeight : 16) + 4;

    qdSCB = GetMasterSCB();
    qdSCB ^= 0x80;
    hOffset = (qdSCB & 0x80) ? 2 : 1;
    Data->hOffset = hOffset;

    icnRect.v1 = destRect.v1 = colorRect.v1 = textRect.v1 = toolRect.v1 = 2;
    destRect.v2 = colorRect.v2 = textRect.v2 = toolRect.v2 = 2;

    toolRect.h1 = 2 * hOffset;
    toolRect.h2 = toolRect.h1 + (10 * hOffset);

    destRect.h1 = colorRect.h1 = toolRect.h2 + (2 * hOffset);
    destRect.h2 = colorRect.h2 = colorRect.h1 + (10 * hOffset);

    InsetRect(&destRect, 2 * dataP->hOffset, 2); (allow for frame around colors)

    colorSetRect.h1 = destRect.h1;      /* color box */
    colorSetRect.h2 = destRect.h2 / 2;
    colorMaskRect.v1 = colorSetRect.v1 = destRect.v1;
    colorMaskRect.v2 = colorSetRect.v2 = destRect.v2;
    colorMaskRect.h1 = colorSetRect.h2 + 1; /* mask color box */
    colorMaskRect.h2 = destRect.h2;

    textRect.h1 = colorRect.h2 + (2 * hOffset);
    textRect.h2 = textRect.h1 + 84;  /* no hOffset calc here- 320 mode has
                                        double width characters */

    iconRect.h1 = textRect.h1 + (2 * hOffset);
    iconRect.h2 = iconRect.h1 + iconP->iconWidth;
    iconRect.v2 = iconRect.v1 + iconP->iconHeight;
}


ResizeWIndow
